package com.lzy.cloud.payment.facade;

import com.lzy.cloud.payment.component.pay.AlipayPayCommons;
import com.lzy.cloud.payment.component.pay.PayCommonsContent;
import com.lzy.cloud.payment.component.pay.WeixinPayCommons;
import com.lzy.cloud.payment.constants.BusinessStatus;
import com.lzy.cloud.payment.constants.BusinessStatus.PayWay;
import com.lzy.cloud.payment.constants.CommonConstants;
import com.lzy.cloud.payment.constants.PayDistributeLockPrefix;
import com.lzy.cloud.payment.dtos.pay.BasePayDTO;
import com.lzy.cloud.payment.dtos.pay.CommonPayDTO;
import com.lzy.cloud.payment.dtos.pay.MobileRequestDTO;
import com.lzy.cloud.payment.dtos.pay.PayOrderDTO;
import com.lzy.cloud.payment.dtos.payment.PayInfoDto;
import com.lzy.cloud.payment.dtos.payment.PayRefundInfoDto;
import com.lzy.cloud.payment.entity.PayInfoDetail;
import com.lzy.cloud.payment.entity.PayRefundInfo;
import com.lzy.cloud.payment.pay.weixin.WxPayData;
import com.lzy.cloud.payment.remote.OrderApi;
import com.lzy.cloud.payment.service.PayInfoService;
import com.lzy.cloud.payment.service.PayRefundInfoService;
import com.lzy.cloud.payment.service.SerialNumberService;
import com.lzy.cloud.payment.utils.Common;
import com.lzy.cloud.payment.utils.CommonsUtil;
import com.lzy.framework.core.ensure.Ensure;
import com.lzy.framework.core.utils.DozerUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class PayFacade {
    private static final Logger logger = LoggerFactory.getLogger(PayFacade.class);

    @Autowired
    private AlipayPayCommons alipayPayCommons;

    @Autowired
    private WeixinPayCommons weixinPayCommons;

    @Autowired
    private PayInfoService payInfoService;

    @Autowired
    private PayRefundInfoService payRefundInfoService;

    @Autowired
    private OrderApi orderApi;

    @Autowired
    private SerialNumberService serialNumberService;

    public String payAsyNotify(BasePayDTO bpDTO) {
        switch (bpDTO.getWay()) {
            case PayWay.alipay:
                PayCommonsContent apc = new PayCommonsContent();
                apc.setPayCommons(alipayPayCommons);
                return apc.payAsyNotify(bpDTO);
            case PayWay.weixin:
                PayCommonsContent wpc = new PayCommonsContent();
                wpc.setPayCommons(weixinPayCommons);
                return wpc.payAsyNotify(bpDTO);
            case 2:
                // 緊支持支付、微信
                return null;
        }

        return null;
    }

    public Map<String, Object> payRequestAll(MobileRequestDTO mqDTO) {
        logger.debug("-------------start-----------------");
        Ensure.that(mqDTO.getRequestType()).isNotNull("09000019"); //移动端请求参数requestType不能为空
        Ensure.that(mqDTO.getOrderId()).isNotNull("09000018"); //移动端请求参数orderId订单号不能为空
        switch (mqDTO.getRequestType()) {
            //预付订单请求接口
            case BusinessStatus.BusinessType.prepayOrder:
                return prepayOrder(mqDTO);
            //订单支付状态请求接口
            case BusinessStatus.BusinessType.payStatus:
                return selectPayStatus(mqDTO);
            //退款请求接口
            case BusinessStatus.BusinessType.applyPayRefund:
                return applyPayRefund(mqDTO);
            //龙币充值
            case BusinessStatus.BusinessType.dragonRecharge:
                return payRecharge(mqDTO);
        }
        logger.info("请求参数requestType不合法");
        Ensure.that(true).isFalse("09000007");
        return null;
    }


    /**
     * 订单支付状态
     *
     * @param mqDTO
     * @return
     */
    public Map<String, Object> selectPayStatus(MobileRequestDTO mqDTO) {
        WxPayData data = new WxPayData();
        data.put("serialNumber", mqDTO.getOrderId());
        PayInfoDto payInfoDto = payInfoService.queryPayInfoByOrderId(mqDTO.getOrderId());
        Ensure.that(payInfoDto == null).isFalse("09000003");   //订单号不存在
        if (payInfoDto.getStatus().equals(CommonConstants.OrderPayStatus.NOPAY.getIndex())) {
            data.put("status", CommonConstants.OrderPayStatus.NOPAY.getIndex());
        } else if (payInfoDto.getStatus().equals(CommonConstants.OrderPayStatus.YESPAY.getIndex())) {
            data.put("status", CommonConstants.OrderPayStatus.YESPAY.getIndex());
        }
        return data.toMap();
    }

    /**
     * 退款请求
     *
     * @param mqDTO
     * @return
     */
    public Map<String, Object> applyPayRefund(MobileRequestDTO mqDTO) {
        Map<String, Object> result = new HashMap<String, Object>();
        logger.info("----申请处理退款----订单号:" + mqDTO.getOrderId());
        Ensure.that(mqDTO.getRefundAmount() == null).isFalse("09000078");  //	退款金额不能为空
        Ensure.that(CommonsUtil.isLegalAmountS(mqDTO.getRefundAmount())).isTrue("09000079");   //退款金额不合法
        PayInfoDto payInfoDO = payInfoService.queryPayInfoByOrderId(mqDTO.getOrderId());
        //获取订单支付信息
        Ensure.that(payInfoDO == null).isFalse("09000003");     //订单号不存在
        Ensure.that(payInfoDO.getStatus().equals(CommonConstants.OrderPayStatus.NOPAY)).isFalse("09000012");     //订单未支付
        mqDTO.setAmount(payInfoDO.getAmount().toString());  //设置支付总金额--（微信）
        mqDTO.setType(payInfoDO.getType());
        mqDTO.setTargetType(payInfoDO.getTargetType());
        //查询退款记录是否存在
        PayRefundInfo payRefundInfo = payRefundInfoService.queryPayRefundInfoByOrderId(mqDTO.getOrderId());
        if (payRefundInfo == null) {
            //新增退款记录
            PayRefundInfo priDO = DozerUtils.map(mqDTO,PayRefundInfo.class);
            priDO.setMemberId(payInfoDO.getMemberId());
            priDO.setAmount(payInfoDO.getAmount());
            if(payInfoDO.getWay().equals(PayWay.weixin)){
                priDO.setFee(Common.getRefundFee(new BigDecimal(mqDTO.getRefundAmount())));   //退还微信手续费
            }else{
                priDO.setFee(new BigDecimal(0d));
            }
            Long refundNumber = serialNumberService.createSerialNumber(CommonConstants.PayBusType.refund.getIndex() + "", PayDistributeLockPrefix.REFUND, payInfoDO.getMemberId());
            priDO.setRefundNumber(refundNumber);  //本地退款单号
            int id = payRefundInfoService.createPayRefundInfo(priDO);
            Ensure.that(id > 0).isTrue("09000069");
            mqDTO.setId(priDO.getId());
            mqDTO.setRefundNumber(refundNumber);
        } else {
            mqDTO.setId(payRefundInfo.getId());
            mqDTO.setRefundNumber(payRefundInfo.getRefundNumber());
        }
        logger.info("----准备申请退款---订单号:" + mqDTO.getOrderId() + ",-----金额:" + mqDTO.getRefundAmount());
        try {
            switch (payInfoDO.getWay()) {
                case PayWay.alipay:
                    result = alipayPayCommons.applyAlipayPayRefund(mqDTO);
                    return result;
                case PayWay.weixin:
                    result = weixinPayCommons.applyWXPayRefund(mqDTO);
                    return result;
            }
        } catch (Exception e) {
            e.printStackTrace();   //测试
            logger.info("请求退款接口异常" + e);
            Ensure.that(true).isFalse("09000006");
        }
        return null;
    }

    /**
     * 定时任务查询退款订单
     */
    public void updateRefundQueryTask() {
        logger.info("-----------本次退款查询开始----------本次开始时间:" + Common.DateToStr(new Date()));
        //获取所有退款订单   --目前获取所有退款中的数据
        PayRefundInfoDto payRefundInfoDO = new PayRefundInfoDto();
        payRefundInfoDO.setStatus(CommonConstants.PayRefundStatus.DISPOSE.getIndex());  //退款中
        List<PayRefundInfoDto> priDO = payRefundInfoService.queryPayRefundInfo(payRefundInfoDO);
        if (!priDO.isEmpty() && priDO != null) {
            for (PayRefundInfoDto pri : priDO) {
                try {
                    switch (pri.getWay()) {
                        case PayWay.alipay:
                            alipayPayCommons.applyAlipayPayRefundQuery(DozerUtils.map(priDO,PayRefundInfo.class));
                            break;
                        case PayWay.weixin:
                            weixinPayCommons.applyWXPayRefundQuery(DozerUtils.map(priDO,PayRefundInfo.class));
                            break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.info("退款查询异常", e);
                    Ensure.that(true).isFalse("09000016");
                }
            }
        }
        logger.info("-----------本次退款查询完成----------本次结束时间:" + Common.DateToStr(new Date()));
    }

    /**
     * 预付订单
     *
     * @param mqDTO
     * @return
     */
    public Map<String, Object> prepayOrder(MobileRequestDTO mqDTO) {
        Ensure.that(mqDTO.getWay()).isNotNull("09000024");  //支付方式不能为空
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        //查询未付款订单
        PayInfoDto payInfoDO = payInfoService.queryPayInfoByOrderId(mqDTO.getOrderId());
        //支付
        if (payInfoDO == null) {
            payOrderDTO = DozerUtils.map(orderApi.findOrderByOrderId(mqDTO.getOrderId()).getResult(),PayOrderDTO.class);
            Ensure.that(payOrderDTO).isNotNull("09000006");
            //生成支付预付订单
            mqDTO.setPayOrderDTO(payOrderDTO);
            PayInfoDto payInfoDto = PayInfoDto.convert(mqDTO);
            payInfoDto.setBalancePaid(mqDTO.getBalancePaid() == null ? BigDecimal.ZERO : mqDTO.getBalancePaid());
            payInfoDto.setIntegration(new BigDecimal(mqDTO.getIntegration() == null ? 0 : mqDTO.getIntegration()));
            payInfoDto.setPayAmount(mqDTO.getPayAmount() == null ? BigDecimal.ZERO : mqDTO.getPayAmount());
            int count = payInfoService.createPayInfo(payInfoDto);
            Ensure.that(CommonsUtil.isEmpty(count)).isFalse("09000023"); //新增支付记录失败
        } else {
            Ensure.that(payInfoDO.getStatus() > 0).isFalse("09000008");   //该订单已支付
            payOrderDTO.setOrderId(payInfoDO.getSerialNumber());
            payOrderDTO.setOrderAmount(payInfoDO.getAmount());
            payOrderDTO.setSkuName(CommonConstants.SKU_NAME);
            mqDTO.setPayOrderDTO(payOrderDTO);
        }
        //测试数据
//        payOrderDTO.setOrderAmount(BigDecimalUtil.to2Point(new BigDecimal(0.01)));
        //转化公共支付
        CommonPayDTO commonPayDTO = new CommonPayDTO();
        commonPayDTO.setSerialNumber(mqDTO.getPayOrderDTO().getOrderId() + "");
        commonPayDTO.setSkuName(mqDTO.getPayOrderDTO().getSkuName());
        commonPayDTO.setAmount(mqDTO.getPayOrderDTO().getOrderAmount());
        commonPayDTO.setTradeType(CommonConstants.APP);
        switch (mqDTO.getWay()) {
            case PayWay.alipay:
                return alipayPayCommons.prepayOrder(commonPayDTO);
            case PayWay.weixin:
                return weixinPayCommons.prepayOrder(commonPayDTO);
            case 2:
                // 緊支持支付、微信
                return null;
        }

        return null;
    }

    /**
     * 移动端调用充值
     *
     * @param mqDTO
     * @return
     */
    public Map<String, Object> payRecharge(MobileRequestDTO mqDTO) {
        WxPayData data = new WxPayData();
        Ensure.that(mqDTO.getAmount()).isNotNull("09000021");                           //充值金额不能为空
        Ensure.that(CommonsUtil.isLegalNumber(mqDTO.getAmount())).isTrue("09000022");   //充值金额不合法
        //生成订单号
        Long serailNumber = serialNumberService.createSerialNumber(CommonConstants.PayBusType.recharge.getIndex() + "", PayDistributeLockPrefix.PAY, Long.parseLong(mqDTO.getMemberId()));
        mqDTO.setOrderId(String.valueOf(serailNumber));
        int count = payInfoService.createPayInfo(DozerUtils.map(mqDTO,PayInfoDto.class));
        Ensure.that(CommonsUtil.isEmpty(count)).isFalse("09000023");
        data.put("serialNumber", mqDTO.getOrderId());
        data.put("amount", mqDTO.getAmount());
        data.put("status", CommonConstants.OrderPayStatus.NOPAY.getIndex());
        data.put("skuName", CommonConstants.SKU_NAME);
        return data.toMap();
    }

    /**
     * 公共支付--APP支付
     */
    public Map<String, Object> createCommonPayRequest(CommonPayDTO commonPayDTO) {
        //初始化
        createCommonPayValidate(commonPayDTO);

        //预付订单
        switch (commonPayDTO.getWay()) {
            case PayWay.alipay:
                return alipayPayCommons.prepayOrder(commonPayDTO);
            case PayWay.weixin:
                commonPayDTO.setTradeType(CommonConstants.APP);
                return weixinPayCommons.prepayOrder(commonPayDTO);
            case 2:
                // 緊支持支付、微信
                return null;
        }
        return null;
    }

    /**
     * 预付订单公共支付验证
     *
     * @param commonPayDTO
     */
    public void createCommonPayValidate(CommonPayDTO commonPayDTO) {
        //验证参数是否正确
        Ensure.that(commonPayDTO.getSerialNumber() == null).isFalse("09000018");   //订单号不能为空
        Ensure.that(StringUtils.isBlank(commonPayDTO.getSkuName())).isFalse("09000074");  //商品名称不能为空
        Ensure.that(commonPayDTO.getWay() == 0 || commonPayDTO.getWay() == 1).isTrue("09000075");  //支付类型参数不合法
        Ensure.that(commonPayDTO.getType() == null).isFalse("09000081");  //交易类型参数不合法
        Ensure.that(commonPayDTO.getAmount() == null).isFalse("09000072");  //	交易金额不能为空
        Ensure.that(CommonsUtil.isLegalAmount(commonPayDTO.getAmount())).isTrue("09000076");   //交易金额不合法

        //查询订单
        PayInfoDto payInfoDO = payInfoService.queryPayInfoByOrderId(commonPayDTO.getSerialNumber());
        if (payInfoDO == null) {
            //生成订单
            int count = payInfoService.createPayInfo(PayInfoDto.commonPayConvert(commonPayDTO));
            Ensure.that(CommonsUtil.isEmpty(count)).isFalse("09000023"); //新增支付记录失败
        } else {
            //查询是否已支付
            Ensure.that(payInfoDO.getStatus() > 0).isFalse("09000008");   //该订单已支付
        }
    }

//    public static void main(String[] args) {
//        /*System.out.println(Common.getRefundFee(new BigDecimal(1)));
//        System.out.println(StringUtils.isBlank(null));*/
//        System.out.println(CommonConstants.CommonTradeType.getName(5));
//    }
}
